import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

import 'package:flutter_note/note/bean.dart';
import 'package:flutter_note/note/const.dart';
import 'package:flutter_note/note/utils.dart';

class StadiumEditView extends StatelessWidget {
  final TextEditingController controller;
  final String hintText;
  final IconData icons;
  final bool isObscureText;

  StadiumEditView(
      this.controller, this.hintText, this.icons, this.isObscureText);

  @override
  Widget build(BuildContext context) {
    return Material(
      color: color.transparent,
      shape: StadiumBorder(
          side: BorderSide(
        color: color.green,
      )),
      child: Theme(
        // Create a unique theme with "new ThemeData"
        data: ThemeData(
          cursorColor: Colors.green,
          primaryColor: Colors.green,
        ),
        child: TextField(
          controller: controller,
          keyboardType: TextInputType.text,
          style: TextStyle(fontSize: dim.t16, color: color.txt3),
          obscureText: isObscureText,
          decoration: InputDecoration(
            prefixIcon: Icon(icons),
            border: InputBorder.none,
            hintText: hintText,
            contentPadding: EdgeInsets.only(
                left: dim.x15, right: dim.x15, top: dim.x10, bottom: dim.x10),
          ),
        ),
      ),
    );
  }
}

class SettingView extends StatelessWidget {
  final String firstText;
  final String secondText;
  final VoidCallback onPressed;

  SettingView(this.firstText, this.secondText, this.onPressed);

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      shape: BorderDirectional(),
      color: color.white,
      elevation: 0.0,
      highlightElevation: 0.0,
      padding: EdgeInsets.all(0.0),
      onPressed: onPressed,
      child: Container(
        height: dim.x50,
        padding: EdgeInsets.only(left: dim.x15, right: dim.x15),
        child: Row(
          children: <Widget>[
            Text(
              firstText,
              style: TextStyle(
                color: color.txt3,
                fontSize: dim.t16,
              ),
            ),
            Space(Const.SPACE_NULL),
            Text(
              secondText,
              style: TextStyle(
                color: color.txt9,
                fontSize: dim.t16,
              ),
            ),
            Center(
              child: Icon(Icons.keyboard_arrow_right, color: color.txt9),
            ),
          ],
        ),
      ),
    );
  }
}

class ClipImageView extends StatelessWidget {
  final String url;
  final double widthSize;
  final double heightSize;
  final int type;

  ClipImageView(this.url, this.widthSize, this.heightSize, this.type);

  @override
  Widget build(BuildContext context) {
    if (url == null || url.isEmpty) {
      if (type == Const.IMG_SIZE_HEAD) {
        return Icon(
          Icons.account_circle,
          color: color.grey,
          size: widthSize,
        );
      } else if (type == Const.IMG_SIZE_PIC) {
        return Icon(
          Icons.image,
          color: color.grey,
          size: 0,
        );
      } else {
        return Icon(
          Icons.image,
          color: color.grey,
          size: widthSize,
        );
      }
    } else {
      if (type == Const.IMG_SIZE_HEAD || type == Const.IMG_SIZE_NOTE) {
        return Container(
          decoration: new BoxDecoration(
            border: new Border.all(color: color.a6_grey, width: dim.x1),
            borderRadius: BorderRadius.all(Radius.circular(widthSize)),
          ),
          child: ClipOval(
            child: Image.network(Const.BASE_HOST + Const.IMG_PATH + url,
                fit: BoxFit.cover, width: widthSize, height: heightSize),
          ),
        );
      } else {
        return ClipRRect(
          borderRadius: BorderRadius.all(new Radius.circular(dim.x10)),
          child: Image.network(Const.BASE_HOST + Const.IMG_PATH + url,
              fit: BoxFit.cover, width: widthSize, height: heightSize),
        );
      }
    }
  }
}

class NoteView extends StatelessWidget {
  final ReplyNote note;
  final VoidCallback onPressed;

  NoteView(this.note, this.onPressed);

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      shape: BorderDirectional(),
      color: color.white,
      elevation: 0.0,
      highlightElevation: 0.0,
      padding: EdgeInsets.all(0.0),
      onPressed: onPressed,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Container(
              padding: EdgeInsets.only(left: dim.x5, top: dim.x5),
              child: ClipImageView(
                  note.user.head, dim.x30, dim.x30, Const.IMG_SIZE_HEAD)),
          Expanded(
            child: Container(
              padding: EdgeInsets.only(top: dim.x5, right: dim.x5),
              child: Column(
                children: <Widget>[
                  Container(
                    height: dim.x30,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Container(
                          alignment: Alignment.topCenter,
                          padding: EdgeInsets.only(left: dim.x5),
                          child: Text("${note.user.name}",
                              style: TextStyle(
                                  fontSize: dim.t14,
                                  color: color.txt3,
                                  fontWeight: FontWeight.bold)),
                        ),
                        Container(
                          alignment: Alignment.topCenter,
                          child: Text(
                              EmptyUtils.isEmpty(note.book.title)
                                  ? ""
                                  : "《${note.book.title}》",
                              style: TextStyle(
                                  fontSize: dim.t12, color: color.txt6)),
                        ),
                        Space(Const.SPACE_NULL),
                        Container(
                          alignment: Alignment.topCenter,
                          child: Text(
                            DateUtils.msToHm(note.nTime),
                            style:
                                TextStyle(fontSize: dim.t12, color: color.txt6),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Container(
                    alignment: Alignment.centerLeft,
                    child: Padding(
                      padding: EdgeInsets.only(left: dim.x30),
                      child: Text("${note.content}",
                          style:
                              TextStyle(fontSize: dim.t14, color: color.txt3)),
                    ),
                  ),
                  Space(Const.SPACE_TOP, size: dim.x5),
                  Container(
                    alignment: Alignment.centerLeft,
                    child: Padding(
                      padding: EdgeInsets.only(left: dim.x30),
                      child: ClipImageView(
                          note.pic, dim.x150, dim.x150, Const.IMG_SIZE_PIC),
                    ),
                  ),
                  Space(Const.SPACE_TOP, size: dim.x5),
                  Divider(
                    height: dim.x01,
                    color: color.line,
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class CommentView extends StatelessWidget {
  final ReplyComment comment;
  final VoidCallback onPressed;

  CommentView(this.comment, this.onPressed);

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      shape: BorderDirectional(),
      color: color.white,
      elevation: 0.0,
      highlightElevation: 0.0,
      padding: EdgeInsets.all(0.0),
      onPressed: onPressed,
      child: Column(
        children: <Widget>[
          Container(
            padding: EdgeInsets.all(dim.x5),
            child: Column(
              children: <Widget>[
                Container(
                  height: dim.x30,
                  child: Row(
                    mainAxisSize: MainAxisSize.max,
                    children: <Widget>[
                      ClipImageView(comment.user.head, dim.x30, dim.x30,
                          Const.IMG_SIZE_HEAD),
                      Container(
                        alignment: Alignment.topCenter,
                        child: Padding(
                          padding: EdgeInsets.only(left: dim.x5),
                          child: Text("${comment.user.name}",
                              style: TextStyle(
                                  fontSize: dim.t14,
                                  color: color.txt3,
                                  fontWeight: FontWeight.bold)),
                        ),
                      ),
                      Space(Const.SPACE_NULL),
                      Container(
                        alignment: Alignment.topCenter,
                        child: Text(
                          DateUtils.msToHm(comment.cTime),
                          style:
                              TextStyle(fontSize: dim.t12, color: color.txt6),
                        ),
                      ),
                    ],
                  ),
                ),
                Container(
                  alignment: Alignment.centerLeft,
                  child: Padding(
                    padding: EdgeInsets.only(left: dim.x30),
                    child: Text("${comment.msg}",
                        style: TextStyle(fontSize: dim.t14, color: color.txt3)),
                  ),
                ),
                Space(Const.SPACE_TOP, size: dim.x5),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class Space extends StatelessWidget {
  final int type;
  final num size;

  const Space(this.type, {this.size = dim.x20});

  @override
  Widget build(BuildContext context) {
    switch (type) {
      case Const.SPACE_NULL:
        return Expanded(
          child: Container(),
        );
      case Const.SPACE_TOP:
        return Padding(
          padding: EdgeInsets.only(top: size),
        );
      case Const.SPACE_BOTTOM:
        return Padding(
          padding: EdgeInsets.only(bottom: size),
        );
      case Const.SPACE_LEFT:
        return Padding(
          padding: EdgeInsets.only(left: size),
        );
      case Const.SPACE_RIGHT:
        return Padding(
          padding: EdgeInsets.only(right: size),
        );
    }
  }
}

class EnsureVisibleWhenFocused extends StatefulWidget {
  const EnsureVisibleWhenFocused({
    Key key,
    @required this.child,
    @required this.focusNode,
    this.curve: Curves.ease,
    this.duration: const Duration(milliseconds: 100),
  }) : super(key: key);

  /// The node we will monitor to determine if the child is focused
  final FocusNode focusNode;

  /// The child widget that we are wrapping
  final Widget child;

  /// The curve we will use to scroll ourselves into view.
  ///
  /// Defaults to Curves.ease.
  final Curve curve;

  /// The duration we will use to scroll ourselves into view
  ///
  /// Defaults to 100 milliseconds.
  final Duration duration;

  @override
  _EnsureVisibleWhenFocusedState createState() =>
      new _EnsureVisibleWhenFocusedState();
}

///
/// We implement the WidgetsBindingObserver to be notified of any change to the window metrics
///
class _EnsureVisibleWhenFocusedState extends State<EnsureVisibleWhenFocused>
    with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    widget.focusNode.addListener(_ensureVisible);
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    widget.focusNode.removeListener(_ensureVisible);
    super.dispose();
  }

  ///
  /// This routine is invoked when the window metrics have changed.
  /// This happens when the keyboard is open or dismissed, among others.
  /// It is the opportunity to check if the field has the focus
  /// and to ensure it is fully visible in the viewport when
  /// the keyboard is displayed
  ///
  @override
  void didChangeMetrics() {
    if (widget.focusNode.hasFocus) {
      _ensureVisible();
    }
  }

  ///
  /// This routine waits for the keyboard to come into view.
  /// In order to prevent some issues if the Widget is dismissed in the
  /// middle of the loop, we need to check the "mounted" property
  ///
  /// This method was suggested by Peter Yuen (see discussion).
  ///
  Future<Null> _keyboardToggled() async {
    if (mounted) {
      EdgeInsets edgeInsets = MediaQuery.of(context).viewInsets;
      while (mounted && MediaQuery.of(context).viewInsets == edgeInsets) {
        await new Future.delayed(const Duration(milliseconds: 10));
      }
    }

    return;
  }

  Future<Null> _ensureVisible() async {
    // Wait for the keyboard to come into view
    await Future.any([
      new Future.delayed(const Duration(milliseconds: 300)),
      _keyboardToggled()
    ]);

    // No need to go any further if the node has not the focus
    if (!widget.focusNode.hasFocus) {
      return;
    }

    // Find the object which has the focus
    final RenderObject object = context.findRenderObject();
    final RenderAbstractViewport viewport = RenderAbstractViewport.of(object);
    assert(viewport != null);

    // Get the Scrollable state (in order to retrieve its offset)
    ScrollableState scrollableState = Scrollable.of(context);
    assert(scrollableState != null);

    // Get its offset
    ScrollPosition position = scrollableState.position;
    double alignment;

    if (position.pixels > viewport.getOffsetToReveal(object, 0.0).offset) {
      // Move down to the top of the viewport
      alignment = 0.0;
    } else if (position.pixels <
        viewport.getOffsetToReveal(object, 1.0).offset) {
      // Move up to the bottom of the viewport
      alignment = 1.0;
    } else {
      // No scrolling is necessary to reveal the child
      return;
    }

    position.ensureVisible(
      object,
      alignment: alignment,
      duration: widget.duration,
      curve: widget.curve,
    );
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}
